package com.eg366.selfFrame.core;

import java.util.HashMap;
import java.util.Map;

import com.eg366.selfFrame.advisor.SelfAdvisor;
import com.eg366.selfFrame.annotation.Bean;
import com.eg366.selfFrame.annotation.IsAspect;
import com.eg366.selfFrame.proxy.AopProxy;
import com.eg366.selfFrame.proxy.AopSupport;
import com.eg366.selfFrame.proxy.CgLibAopProxy;
import com.eg366.selfFrame.proxy.JdkDynamicAopProxy;

/**
 * aop工厂bean
 * 
 * @author eg366
 */
public class AopFactoryBean {

	/* key:advisorId */
	private Map<String, SelfAdvisor> aopAdvisorMap = new HashMap<String, SelfAdvisor>();

	private static AopFactoryBean afb;

	private AopFactoryBean() {
	}

	public static AopFactoryBean getInstance() {
		if (afb == null)
			afb = new AopFactoryBean();
		return afb;
	}

	public Object getObject(Object target) {
		Object obj = createProxyObj(target);
		return obj;
	}

	/**
	 * 创建AOP代理对象
	 */
	private Object createProxyObj(Object target) {
		AopSupport aopSupport = buildAopSupport(target);
		aopSupport.setAopAdvisorMap(aopAdvisorMap);
		Class<?> clazz = target.getClass();
		Class<?>[] interfaces = clazz.getInterfaces();
		/* 通过jdk动态代理方式或者cglib方式 */
		if (interfaces.length == 0 || clazz.getAnnotation(Bean.class).useCglib()) {
			return createProxyByCglib(aopSupport);
		} else {
			return createProxyByJdkDynamic(aopSupport);
		}
	}

	/**
	 * 创建aop辅助对象
	 */
	private AopSupport buildAopSupport(Object target) {
		return new AopSupport(target);
	}

	/**
	 * 通过jdk动态代理创建代理对象
	 */
	private Object createProxyByJdkDynamic(AopSupport aopSupport) {
		Object obj = null;
		AopProxy aopProxy = new JdkDynamicAopProxy(aopSupport);
		obj = aopProxy.getProxy(Thread.currentThread().getContextClassLoader());
		return obj;
	}

	/**
	 * 通过cglib创建代理对象
	 */
	private Object createProxyByCglib(AopSupport aopSupport) {
		Object obj = null;
		AopProxy aopProxy = new CgLibAopProxy(aopSupport);
		obj = aopProxy.getProxy(Thread.currentThread().getContextClassLoader());
		return obj;
	}

	public void initAopAdvisor(SelfAdvisor[] selfAdvisors) {
		try {
			for (SelfAdvisor adv : selfAdvisors) {
				IsAspect aspectAnno = adv.getClass().getAnnotation(IsAspect.class);
				aopAdvisorMap.put(aspectAnno.id(), adv);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
